home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 2111 < prev    next >
Encoding:
Text File  |  1996-08-05  |  12.3 KB  |  299 lines

  1. Path: fohnix.metronet.com!not-for-mail
  2. From: milam@fohnix.metronet.com (Stan Milam)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: Comma Delimited function wanted
  5. Date: 18 Jan 1996 19:43:12 -0600
  6. Organization: Texas Metronet, Inc  (login info (214/488-2590 - 817/571-0400))
  7. Message-ID: <4dmsvg$gqe@fohnix.metronet.com>
  8. References: <4d1l42$mb6@voyager.Internex.NET> <4d4gic$p7u@umbc9.umbc.edu> <4d6gi2$g4r@news.iag.net>
  9. NNTP-Posting-Host: fohnix.metronet.com
  10. X-Newsreader: TIN [version 1.2 PL2]
  11.  
  12. John R Buchan (jatmon@iag.net) wrote:
  13. : In article <4d4gic$p7u@umbc9.umbc.edu>, schlein@umbc.edu says...
  14. : <snip>
  15. : >#include <stdio.h>
  16. : >
  17. : >int main (void)
  18. : >{
  19. : >  char *buffer = "3740067099,914885AC2,P03,5000";  
  20. : >  char  field1[20],
  21. : >        field2[20],
  22. : >        field3[20],
  23. : >        field4[20];
  24. : >
  25. : >  sscanf (buffer, "%[^,],%[^,],%[^,],%s", field1, field2, field3, field4);
  26. : >  printf ("field1 = %s\n", field1);
  27. : >  printf ("field2 = %s\n", field2);
  28. : >  printf ("field3 = %s\n", field3);
  29. : >  printf ("field4 = %s\n", field4);
  30. : >
  31. : >  return (0);
  32. : >}
  33.  
  34. : This works fine, unless it runs into something like:
  35.  
  36. :   char *buffer = "3740067099,,P03,5000";  
  37.  
  38. : A strtok based solution will have a similar problem.  A full solution to 
  39. : this type of parsing will require a non-standard function (custom code).
  40.  
  41. Here are three custom code functions.
  42.  
  43.  
  44. /*FILE*****************************************************************/
  45. /* File Id:                    strptok.c.                             */
  46. /* Author:                     Stan Milam.                            */
  47. /* Date Written:               25-Apr-95.                             */
  48. /* Description:                                                       */
  49. /*     Implement a strtok() like function which preserves the original*/
  50. /*     string.                                                        */
  51. /*                                                                    */
  52. /*****************************************************************FILE*/
  53.  
  54. #include <stddef.h>
  55. #include <string.h>
  56.  
  57. /*FUNCTION*************************************************************/
  58. /* Name: strptok().                                                   */
  59. /*                                                                    */
  60. /* Description:                                                       */
  61. /*     This function implements a strtok() like function which pre-   */
  62. /*     serves the original string and copies tokens into a programmer */
  63. /*     supplied buffer.                                               */
  64. /*                                                                    */
  65. /* Arguments:                                                         */
  66. /*     char *dest - Address of buffer where token is to be copied.    */
  67. /*     char *src  - Address of source buffer where tokens are to be   */
  68. /*                  extracted.                                        */
  69. /*     char *brk  - "Break" characters which delimit tokens.          */
  70. /*                                                                    */
  71. /* Return Value:                                                      */
  72. /*     NULL when the end of the string is encounted or when the src   */
  73. /*     argument is NULL or empty.  Otherwise the address just beyond  */
  74. /*     the last token found in the source string.                     */
  75. /*                                                                    */
  76. /*************************************************************FUNCTION*/
  77.  
  78. char *strptok( char *dest, char *src, char *brk ) {
  79.  
  80.     unsigned len;
  81.     char *rv, *wrk;
  82.  
  83.     /******************************************************************/
  84.     /* Make sure destination is empty and check for a valid source.   */
  85.     /******************************************************************/
  86.  
  87.     dest[0] = '\0';
  88.     if ( src == NULL || *src == '\0' )
  89.         rv = NULL;
  90.  
  91.     /******************************************************************/
  92.     /* If there are not any break characters set rv to NULL and copy  */
  93.     /* the remaining characters to the destination.                   */
  94.     /******************************************************************/
  95.  
  96.     else if (( wrk = strpbrk(src, brk) ) == NULL) {
  97.         rv = NULL;
  98.         strcpy( dest, src );
  99.     }
  100.     
  101.     /******************************************************************/
  102.     /* If the first character of source is a break character then     */
  103.     /* skip over it.                                                  */
  104.     /******************************************************************/
  105.  
  106.     else if ( src == wrk )
  107.         rv = src + 1;
  108.  
  109.     /******************************************************************/
  110.     /* Found a token! Compute return value, length of token and copy  */
  111.     /* it to destination making sure it is null terminated.           */
  112.     /******************************************************************/
  113.  
  114.     else {
  115.         rv = wrk + 1;
  116.         len = wrk - src;
  117.         strncpy( dest, src, len )[len] = '\0';
  118.     }
  119.     return rv;
  120. }
  121.  
  122. #ifdef TEST
  123. #include <stdio.h>
  124. int main( void ) {
  125.  
  126.     char dest[50] = "", *rv;
  127.     char *src = ":tsdsstm:243::0:Stan Milam,3730442330,Y:/u/tsdsstm/ksh";
  128.  
  129.     rv = strptok( dest, NULL, ":" );
  130.     rv = strptok( dest, "",   ":" );
  131.  
  132.     rv = strptok( dest, src, ":" );
  133.     while ( rv || dest[0] ) {
  134.         printf(":%s:\n", dest);
  135.         rv = strptok( dest, rv, ":" );
  136.     }
  137. }
  138. #endif
  139.  
  140. /**********************************************************************/
  141. /* File Id:                     strparse.c.                           */
  142. /* Author:                      Stan Milam.                           */
  143. /* Date Written:                20-Feb-1995.                          */
  144. /* Description:                                                       */
  145. /*     The str_parse() function is used to extract fields from de-    */
  146. /*     limited ASCII records. It is designed to deal with empty fields*/
  147. /*     in a logical manner and meant to preclude the use of strtok()  */
  148. /*     for such purposes!                                             */
  149. /*                                                                    */
  150. /* Arguments:                                                         */
  151. /*     char **str       - The address of a pointer which in turn      */
  152. /*                        points to the string being parsed. The      */
  153. /*                        actual pointer is modified with each call to*/
  154. /*                        point to the beginning of the next field.   */
  155. /*     char *delimiters - The address of the string containing the    */
  156. /*                        characters used to delimit the fields within*/
  157. /*                        the record.                                 */
  158. /*                                                                    */
  159. /* Return Value:                                                      */
  160. /*     A pointer of type char which points to the current field in the*/
  161. /*     parsed string.  If an empty field is encountered the address   */
  162. /*     is that of an empty string (i.e. "" ). When there are no more  */
  163. /*     fields in the record a NULL pointer value is returned.         */
  164. /*                                                                    */
  165. /**********************************************************************/
  166.  
  167. #include <stddef.h>
  168. #include <string.h>
  169.  
  170. char *str_parse( char **str, char *delimiters ) {
  171.  
  172.     char *head, *tail, *rv;
  173.  
  174.     if ( *str == NULL || **str == '\0' )
  175.         rv = NULL;
  176.     else if ( delimiters == NULL || *delimiters == '\0' )
  177.         rv = NULL;
  178.     else {
  179.         rv = head = *str;
  180.         if ( ( tail = strpbrk( head, delimiters ) ) == NULL )
  181.             *str = head + strlen( head );
  182.         else {
  183.             *tail = '\0';
  184.             *str = tail + 1;
  185.         }
  186.     }
  187.     return rv;
  188. }
  189.  
  190. #ifdef TEST
  191. #include <stdio.h>
  192. #include <assert.h>
  193.  
  194. int main( void ) {
  195.  
  196.     char *wrk, *rv;
  197.     char delimiters[] = ":;";
  198.     char wrkstr[] = "1:2::4:;6:7";
  199.  
  200.     wrk = "";
  201.     assert( str_parse( NULL, delimiters ) == NULL );
  202.     assert( str_parse( &wrk, delimiters ) == NULL );
  203.  
  204.     wrk = wrkstr;
  205.     assert( str_parse( &wrk, NULL ) == NULL );
  206.     assert( str_parse( &wrk, "" ) == NULL );
  207.  
  208.     while((rv = str_parse( &wrk, delimiters )))
  209.         puts( rv );
  210.  
  211.     return 0;
  212. }
  213. #endif
  214.  
  215.  
  216. /**********************************************************************/
  217. /* File Id:                     strcut.c.                             */
  218. /* Author:                      Stan Milam.                           */
  219. /* Date Written:                5-Nov-94.                             */
  220. /*                                                                    */
  221. /* ********************************************************************/
  222.  
  223. #include <string.h>
  224. #include "toolbox.h"
  225.  
  226. /**********************************************************************/
  227. /* Name: strcut()                                                     */
  228. /*                                                                    */
  229. /* Description:                                                       */
  230. /*     This function will surgically cut delimited fields from a      */
  231. /*     source string, placing the resulting string into a destination */
  232. /*     address.  All fields in the source string must be delimited by */
  233. /*     the same character.  A good example is the colon (:) delimited */
  234. /*     fields in the /etc/passwd file in UNIX systems.                */
  235. /*                                                                    */
  236. /* Arguments:                                                         */
  237. /*     char     *dest     - The destination address to place the re-  */
  238. /*                          sulting string.                           */
  239. /*     char     *source   - The string containing the delimited fields*/
  240. /*     int      delimiter - Character which delimites the fields.     */
  241. /*     unsigned field     - The field to extract from source string.  */
  242. /*                                                                    */
  243. /* Return Value:                                                      */
  244. /*     The address of the destination string.                         */
  245. /*                                                                    */
  246. /**********************************************************************/
  247.  
  248. char *strcut( char *dest, char *source, int delimiter, unsigned field ) {
  249.  
  250.     unsigned count, fld_max;
  251.     char     *wrk, *head, *tail;
  252.  
  253.     /******************************************************************/
  254.     /* Count the number of delimiters.  Then number of fields is al-  */
  255.     /* ways one more than the delimiters.                             */
  256.     /******************************************************************/
  257.  
  258.     count = chrcount( source, delimiter );
  259.     fld_max = count + 1;
  260.  
  261.     /******************************************************************/
  262.     /* Do some sanity checks. Get out if there is no field, or no de- */
  263.     /* limiter, or if we are going after a field that does not exist. */
  264.     /******************************************************************/
  265.  
  266.     if ( (field == 0 || count == 0) || (field > fld_max) )
  267.         *dest = '\0';
  268.     else {
  269.  
  270.         /**************************************************************/
  271.         /* Initialize our head pointer and using the delimiters work  */
  272.         /* our way to the field we want.                              */
  273.         /**************************************************************/
  274.  
  275.         for ( head = source, count = 0; count < field; count++ ) {
  276.             tail = head;
  277.             wrk = strchr( head, delimiter );
  278.  
  279.             /**********************************************************/
  280.             /* If we are on the last field we must point work at the  */
  281.             /* null character, else point head one character past the */
  282.             /* current delimiter at the start of the next field.      */
  283.             /**********************************************************/
  284.  
  285.             if ( wrk == NULL ) wrk = head + strlen( head );
  286.             else head = wrk + 1;
  287.         }
  288.  
  289.         /**************************************************************/
  290.         /* At this point wrk is at the end of the field and tail is at*/
  291.         /* the beginning.  Get number of characters between and copy. */
  292.         /**************************************************************/
  293.  
  294.         count = ((unsigned) wrk) - ((unsigned) tail);
  295.         strncpy( dest, tail, count )[count] = '\0';
  296.     }
  297.     return dest;
  298. }
  299.